<!DOCTYPE html>


<html lang="zh-CN">


<head>
  <meta charset="utf-8" />
    
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <title>
    用 Python 操作 Redis，看这一篇就够了.md |  
  </title>
  <meta name="generator" content="hexo-theme-ayer">
  
  <link rel="shortcut icon" href="/favicon.ico" />
  
  
<link rel="stylesheet" href="/dist/main.css">

  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css">

  
<link rel="stylesheet" href="/css/custom.css">

  
  
<script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>

  
  

  

</head>

</html>

<body>
  <div id="app">
    
      
    <main class="content on">
      <section class="outer">
  <article
  id="post-develop/用 Python 操作 Redis，看这一篇就够了"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  用 Python 操作 Redis，看这一篇就够了.md
</h1>
 

    </header>
     
    <div class="article-meta">
      <a href="/2020/11/11/develop/%E7%94%A8%20Python%20%E6%93%8D%E4%BD%9C%20Redis%EF%BC%8C%E7%9C%8B%E8%BF%99%E4%B8%80%E7%AF%87%E5%B0%B1%E5%A4%9F%E4%BA%86/" class="article-date">
  <time datetime="2020-11-10T16:00:00.000Z" itemprop="datePublished">2020-11-11</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/develop/">develop</a>
  </div>
  
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> 字数统计:</span>
            <span class="post-count">9k</span>
        </span>
    </span>

    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> 阅读时长≈</span>
            <span class="post-count">40 分钟</span>
        </span>
    </span>
</div>
 
    </div>
      
    <div class="tocbot"></div>




  
    <div class="article-entry" itemprop="articleBody">
       
  <h1 id="用-Python-操作-Redis，看这一篇就够了"><a href="#用-Python-操作-Redis，看这一篇就够了" class="headerlink" title="用 Python 操作 Redis，看这一篇就够了"></a>用 Python 操作 Redis，看这一篇就够了</h1><p><img src=""></p>
<p><a target="_blank" rel="noopener" href="https://mp.weixin.qq.com/s?__biz=MzIzMzMzOTI3Nw==&mid=2247491716&idx=1&sn=76a9f3ad5163a9ffdbaf0fefd0259261&chksm=e8858066dff20970fa9988675154fff6a6f84793a80b8ea1d6fe5d5bbb5bc816d2feabc50664&token=253987300&lang=zh_CN&scene=21#wechat_redirect">明哥原创的200页《PyCharm 中文指南》 震撼发布</a></p>
<h2 id="1-前言"><a href="#1-前言" class="headerlink" title="1. 前言"></a>1. 前言</h2><p>前面两篇文章聊到了 Python 处理 Mysql、Sqlite 数据库常用方式，本篇文章继续说另外一种比较常用的数据存储方式：Redis</p>
<p>Redis：Remote Dictionary Server，即：远程字典服务，Redis 底层使用 C 语言编写，是一款开源的、基于内存的 NoSql 数据库</p>
<p>由于 Redis 性能远超其他数据库，并且支持集群、分布式及主从同步等优势，所以经常用于 缓存数据、高速读写 等场景</p>
<p>本篇文章就聊聊 Python 操作 Redis 正确的姿势</p>
<h2 id="2-准备"><a href="#2-准备" class="headerlink" title="2. 准备"></a>2. 准备</h2><p>我们以在云服务器 Centos 7.8 安装 Redis-Server 为例</p>
<p>首先，安装在云服务器上 Redis 数据库</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 下载epel仓库  </span><br><span class="line">yum install epel-release  </span><br><span class="line">  </span><br><span class="line"># 安装redis  </span><br><span class="line">yum install redis  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>然后，通过 vim 命令修改 Redis 配置文件，打开远程连接，设置连接密码  </p>
<p>配置文件目录：/etc/redis.conf</p>
<ul>
<li><p>bind 更改为 0.0.0.0，容许外网访问</p>
</li>
<li><p>requirepass 设置一个访问密码</p>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># vim &#x2F;etc&#x2F;redis.conf  </span><br><span class="line"># 1、bing从127.0.0.1修改为:0.0.0.0，开放远程连接  </span><br><span class="line">bind 0.0.0.0   </span><br><span class="line">  </span><br><span class="line"># 2、设置密码  </span><br><span class="line">requirepass 123456 </span><br></pre></td></tr></table></figure>

<p>需要指出的是，为了保证云服务器数据安全，Redis 开放远程访问的时候，一定要加强密码  </p>
<p>接着，启动 Redis 服务，开启防火墙和端口，配置云服务器安全组</p>
<p>默认情况下，Redis 服务使用的端口号是 6379</p>
<p>另外，需要在云服务器安全组进行配置，保证 Redis 数据库能正常连接</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># 启动Redis服务，默认redis端口号是6379  </span><br><span class="line">systemctl start redis   </span><br><span class="line">  </span><br><span class="line"># 打开防火墙  </span><br><span class="line">systemctl start firewalld.service  </span><br><span class="line">  </span><br><span class="line"># 开放6379端口  </span><br><span class="line">firewall-cmd --zone&#x3D;public --add-port&#x3D;6379&#x2F;tcp --permanent     </span><br><span class="line">  </span><br><span class="line"># 配置立即生效  </span><br><span class="line">firewall-cmd --reload </span><br></pre></td></tr></table></figure>

<p>完成以上操作，我们就可以通过 Redis-CLI 或 Redis 客户端工具进行连接了</p>
<p>最后，要使用 Python 操作 Redis，我们需要使用 pip 安装一个依赖  </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 安装依赖，便于操作redis  </span><br><span class="line">pip3 install redis </span><br></pre></td></tr></table></figure>

<h2 id="3-实战"><a href="#3-实战" class="headerlink" title="3. 实战"></a>3. 实战</h2><p>在操作 Redis 中的数据之前，我们需要利用 Host、端口号、密码实例化一个 Redis 连接对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">from redis import Redis  </span><br><span class="line">  </span><br><span class="line">class RedisF(object):  </span><br><span class="line">  </span><br><span class="line">    def __init__(self):  </span><br><span class="line">        # 实例化Redis对象  </span><br><span class="line">        # decode_responses&#x3D;True，如果不加则写入的为字节类型  </span><br><span class="line">        # host：远程连接地址  </span><br><span class="line">        # port：Redis端口号  </span><br><span class="line">        # password：Redis授权密码  </span><br><span class="line">        self.redis_obj &#x3D; Redis(host&#x3D;&#39;139.199.**.**&#39;,port&#x3D;6379,password&#x3D;&#39;123456&#39;,decode_responses&#x3D;True,charset&#x3D;&#39;UTF-8&#39;, encoding&#x3D;&#39;UTF-8&#39;)  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>接下来我们以操作字符串、列表、set 集合、zset 集合、哈希表、事务为例，讲讲 Python 操作这些数据的方法</p>
<p>1、字符串操作</p>
<p>操作字符串有两种方式，操作方法分别是：set() 和 mset()</p>
<p>其中：set() 一次只能保存一个值，参数意义如下</p>
<ul>
<li><p>name：key，代表键</p>
</li>
<li><p>value：value，待保存的值</p>
</li>
<li><p>ex：过期时间，以秒为单位，如果不设置，则永久不过期；否则，过期则删除</p>
</li>
<li><p>px：过期时间，以毫秒为单位</p>
</li>
<li><p>nx/xx：set 操作是否执行与 name 键是否存在有关  </p>
</li>
</ul>
<p><img src=""></p>
<p>获取值和删除值的操作方法分别为：get(Key)、 delete(Key or Keys) </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"># set()：单字符串操作  </span><br><span class="line"># 添加一个值，并设置超时时间为120s  </span><br><span class="line"> self.redis_obj.set(&#39;name&#39;, &#39;airpython&#39;, ex&#x3D;120)  </span><br><span class="line">  </span><br><span class="line"># get()：获取这个值  </span><br><span class="line">print(self.redis_obj.get(&#39;name&#39;))  </span><br><span class="line">  </span><br><span class="line"># delete()：删除一个值或多个值  </span><br><span class="line">self.redis_obj.delete(&#39;name&#39;)  </span><br><span class="line">print(self.redis_obj.get(&#39;name&#39;))  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>对于多值数据的设置，只需要调用 mset() 方法，将待插入的数据以键值对组成一个字典作为参数即可</p>
<p>同理，Redis 提供了 mget() 方法，可以一次获取多个键的值  </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># mset()：设置多个值  </span><br><span class="line">self.redis_obj.mset(&#123;&quot;foo&quot;: &quot;foo1&quot;, &quot;zoo&quot;: &quot;zoo1&quot;&#125;)  </span><br><span class="line">  </span><br><span class="line"># mget()：获取多个值  </span><br><span class="line">result &#x3D; self.redis_obj.mget(&quot;foo&quot;, &quot;zoo&quot;)  </span><br><span class="line">print(result)</span><br></pre></td></tr></table></figure>

<p>2、列表操作  </p>
<p>Redis 提供了很多方法用于操作列表，其中比较常见的如下：</p>
<ul>
<li><p>lpush/rpush：将一个值或多个值插入到列表头部或尾部，其中，lpush 代表头部插入；rpush 代表尾部插入数据</p>
</li>
<li><p>lset：通过索引，将值插入到列表对应的位置</p>
</li>
<li><p>linsert：在列表元素前面或后面插入数据</p>
</li>
<li><p>lindex：通过索引获取列表中的某一个元素，其中，0 代表第一个元素；-1 代表最后一个元素</p>
</li>
<li><p>lrange：通过制定起始位置和结束位置，从列表中获取指定区域的值</p>
</li>
<li><p>llen：获取列表的长度，如果 Key 对应的列表不存在，返回 0</p>
</li>
<li><p>lpop：移除并返回列表中的第一个元素</p>
</li>
<li><p>rpop：移除并返回列表中的最后一个元素</p>
</li>
</ul>
<p>实例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">def manage_list(self):  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    操作列表  </span><br><span class="line">    :return:  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    # 1、新增一个列表，并左边插入一个数据  </span><br><span class="line">    # 注意：可以一次加入多个元素，也可以一个个元素的加入  </span><br><span class="line">    self.redis_obj.lpush(&#39;company&#39;, &#39;阿里&#39;, &#39;腾讯&#39;, &#39;百度&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 2、移除第一个元素  </span><br><span class="line">    self.redis_obj.lpop(&quot;company&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 3、右边插入数据  </span><br><span class="line">    self.redis_obj.rpush(&#39;company&#39;, &#39;字节跳动&#39;, &#39;小米&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 4、移除最后一个元素  </span><br><span class="line">    self.redis_obj.rpop(&quot;company&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 5、获取列表的长度  </span><br><span class="line">    self.redis_obj.llen(&quot;company&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 6、通过索引，获取列表中的某一个元素（第二个元素）  </span><br><span class="line">    print(&#39;列表中第二个元素是：&#39;, self.redis_obj.lindex(&quot;company&quot;, 1))  </span><br><span class="line">  </span><br><span class="line">    # 7、根据范围，查看列表中所有的值  </span><br><span class="line">    print(self.redis_obj.lrange(&#39;company&#39;, 0, -1))</span><br></pre></td></tr></table></figure>

<p>3、操作 Set 集合</p>
<p>Set 是一个无序的元素集合，集合中的元素不能重复，Redis 同样提供了很多方法，便于操作 Set 集合</p>
<p>其中，比较常用的方法如下：</p>
<ul>
<li><p>sadd：添加元素到集合中，已经存在集合中的元素将被忽略，如果集合不存在，则新建一个集合</p>
</li>
<li><p>scard：返回集合元素的数量</p>
</li>
<li><p>smembers：返回集合中所有元素</p>
</li>
<li><p>srem：移除集合中一个或多个元素，如果元素不存在则忽略</p>
</li>
<li><p>sinter：返回两个集合的交集，结果依然是一个集合</p>
</li>
<li><p>sunion：返回两个集合的并集</p>
</li>
<li><p>sdiff：以第一个集合参数为标准，返回两个集合的差集</p>
</li>
<li><p>sunionstore：计算两个集合的并集，保存到一个新的集合中</p>
</li>
<li><p>sismember：判断集合中是否存在某个元素</p>
</li>
<li><p>spop：随机删除集合中的一个元素，并返回</p>
</li>
</ul>
<p>具体实例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line">def manage_set(self):  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    操作set集合  </span><br><span class="line">    :return:  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    self.redis_obj.delete(&quot;fruit&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 1、sadd：新增元素到集合中  </span><br><span class="line">    # 添加一个元素：香蕉  </span><br><span class="line">    self.redis_obj.sadd(&#39;fruit&#39;, &#39;香蕉&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 再添加两个元素  </span><br><span class="line">    self.redis_obj.sadd(&#39;fruit&#39;, &#39;苹果&#39;, &#39;桔子&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 2、集合元素的数量  </span><br><span class="line">    print(&#39;集合元素数量：&#39;, self.redis_obj.scard(&#39;fruit&#39;))  </span><br><span class="line">  </span><br><span class="line">    # 3、移除一个元素  </span><br><span class="line">    self.redis_obj.srem(&quot;fruit&quot;, &quot;桔子&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 再定义一个集合  </span><br><span class="line">    self.redis_obj.sadd(&quot;fruit_other&quot;, &quot;香蕉&quot;, &quot;葡萄&quot;, &quot;柚子&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 4、获取两个集合的交集  </span><br><span class="line">    result &#x3D; self.redis_obj.sinter(&quot;fruit&quot;, &quot;fruit_other&quot;)  </span><br><span class="line">    print(type(result))  </span><br><span class="line">    print(&#39;交集为：&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 5、获取两个集合的并集  </span><br><span class="line">    result &#x3D; self.redis_obj.sunion(&quot;fruit&quot;, &quot;fruit_other&quot;)  </span><br><span class="line">    print(type(result))  </span><br><span class="line">    print(&#39;并集为：&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 6、差集，以第一个集合为标准  </span><br><span class="line">    result &#x3D; self.redis_obj.sdiff(&quot;fruit&quot;, &quot;fruit_other&quot;)  </span><br><span class="line">    print(type(result))  </span><br><span class="line">    print(&#39;差集为：&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 7、合并保存到新的集合中  </span><br><span class="line">    self.redis_obj.sunionstore(&quot;fruit_new&quot;, &quot;fruit&quot;, &quot;fruit_other&quot;)  </span><br><span class="line">    print(&#39;新的集合为：&#39;, self.redis_obj.smembers(&#39;fruit_new&#39;))  </span><br><span class="line">  </span><br><span class="line">    # 8、判断元素是否存在集合中  </span><br><span class="line">    result &#x3D; self.redis_obj.sismember(&quot;fruit&quot;, &quot;苹果&quot;)  </span><br><span class="line">    print(&#39;苹果是否存在于集合中&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 9、随机从集合中删除一个元素，然后返回  </span><br><span class="line">    result &#x3D; self.redis_obj.spop(&quot;fruit&quot;)  </span><br><span class="line">    print(&#39;删除的元素是:&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 3、集合中所有元素  </span><br><span class="line">    result &#x3D; self.redis_obj.smembers(&#39;fruit&#39;)  </span><br><span class="line">  </span><br><span class="line">    print(&quot;最后fruit集合包含的元素是:&quot;, result)</span><br></pre></td></tr></table></figure>

<p>4、操作 zset 集合</p>
<p>zset 集合相比普通 set 集合，是有序的，zset 集合中的元素包含：值和分数，其中分数用于排序</p>
<p>其中，比较常用的方法如下：</p>
<ul>
<li><p>zadd：往集合中新增元素，如果集合不存在，则新建一个集合，然后再插入数据</p>
</li>
<li><p>zrange：通过起始点和结束点，返回集合中的元素值（不包含分数）;如果设置withscores=True，则返回结果会带上分数</p>
</li>
<li><p>zscore：获取某一个元素对应的分数</p>
</li>
<li><p>zcard：获取集合中元素个数</p>
</li>
<li><p>zrank：获取元素在集合中的索引</p>
</li>
<li><p>zrem：删除集合中的元素</p>
</li>
<li><p>zcount：通过最小值和最大值，判断分数在这个范围内的元素个数</p>
</li>
</ul>
<p>实践代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">def manage_zset(self):  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    操作zset集合  </span><br><span class="line">    :return:  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    self.redis_obj.delete(&quot;fruit&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 往集合中新增元素：zadd()  </span><br><span class="line">    # 三个元素分别是：&quot;banana&quot;, 1&#x2F;&quot;apple&quot;, 2&#x2F;&quot;pear&quot;, 3  </span><br><span class="line">    self.redis_obj.zadd(&quot;fruit&quot;, &quot;banana&quot;, 1, &quot;apple&quot;, 2, &quot;pear&quot;, 3)  </span><br><span class="line">  </span><br><span class="line">    # 查看集合中所有元素（不带分数）  </span><br><span class="line">    result &#x3D; self.redis_obj.zrange(&quot;fruit&quot;, 0, -1)  </span><br><span class="line">    # [&#39;banana&#39;, &#39;apple&#39;, &#39;pear&#39;]  </span><br><span class="line">    print(&#39;集合中的元素（不带分数）有：&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 查看集合中所有元素（带分数）  </span><br><span class="line">    result &#x3D; self.redis_obj.zrange(&quot;fruit&quot;, 0, -1, withscores&#x3D;True)  </span><br><span class="line">    # [(&#39;banana&#39;, 1.0), (&#39;apple&#39;, 2.0), (&#39;pear&#39;, 3.0)]  </span><br><span class="line">    print(&#39;集合中的元素（带分数）有：&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 获取集合中某一个元素的分数  </span><br><span class="line">    result &#x3D; self.redis_obj.zscore(&quot;fruit&quot;, &quot;apple&quot;)  </span><br><span class="line">    print(&quot;apple对应的分数为：&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 通过最小值和最大值，判断分数在这个范围内的元素个数  </span><br><span class="line">    result &#x3D; self.redis_obj.zcount(&quot;fruit&quot;, 1, 2)  </span><br><span class="line">    print(&quot;集合中分数大于1，小于2的元素个数有：&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 获取集合中元素个数  </span><br><span class="line">    count &#x3D; self.redis_obj.zcard(&quot;fruit&quot;)  </span><br><span class="line">    print(&#39;集合元素格式:&#39;, count)  </span><br><span class="line">  </span><br><span class="line">    # 获取元素的值获取索引号  </span><br><span class="line">    index &#x3D; self.redis_obj.zrank(&quot;fruit&quot;, &quot;apple&quot;)  </span><br><span class="line">    print(&#39;apple元素的索引为：&#39;, index)  </span><br><span class="line">  </span><br><span class="line">    # 删除集合中的元素：zrem  </span><br><span class="line">    self.redis_obj.zrem(&quot;fruit&quot;, &quot;apple&quot;)  </span><br><span class="line">    print(&#39;删除apple元素后，剩余元素为：&#39;, self.redis_obj.zrange(&quot;fruit&quot;, 0, -1))  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>4、操作哈希</p>
<p>哈希表中包含很多键值对，并且每一个键都是唯一的</p>
<p>Redis 操作哈希表，下面这些方法比较常用：</p>
<ul>
<li><p>hset：往哈希表中添加一个键值对值</p>
</li>
<li><p>hmset：往哈希表中添加多个键值对值</p>
</li>
<li><p>hget：获取哈希表中单个键的值</p>
</li>
<li><p>hmget：获取哈希表中多个键的值列表</p>
</li>
<li><p>hgetall：获取哈希表中种所有的键值对</p>
</li>
<li><p>hkeys：获取哈希表中所有的键列表</p>
</li>
<li><p>hvals：获取哈表表中所有的值列表</p>
</li>
<li><p>hexists：判断哈希表中，某个键是否存在</p>
</li>
<li><p>hdel：删除哈希表中某一个键值对</p>
</li>
<li><p>hlen：返回哈希表中键值对个数</p>
</li>
</ul>
<p>对应的操作代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">def manage_hash(self):  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    操作哈希表  </span><br><span class="line">    哈希：一个键对应一个值，并且键不容许重复  </span><br><span class="line">    :return:  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    self.redis_obj.delete(&quot;website&quot;)  </span><br><span class="line">  </span><br><span class="line">    # 1、新建一个key为website的哈希表  </span><br><span class="line">    # 往里面加入数据：baidu（field），www.baidu.com(value)  </span><br><span class="line">    self.redis_obj.hset(&#39;website&#39;, &#39;baidu&#39;, &#39;www.alibababaidu.com&#39;)  </span><br><span class="line">    self.redis_obj.hset(&#39;website&#39;, &#39;google&#39;, &#39;www.google.com&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 2、往哈希表中添加多个键值对  </span><br><span class="line">    self.redis_obj.hmset(&quot;website&quot;, &#123;&quot;tencent&quot;: &quot;www.qq.com&quot;, &quot;alibaba&quot;: &quot;www.taobao.com&quot;&#125;)  </span><br><span class="line">  </span><br><span class="line">    # 3、获取某一个键的值  </span><br><span class="line">    result &#x3D; self.redis_obj.hget(&quot;website&quot;, &#39;baidu&#39;)  </span><br><span class="line">    print(&quot;键为baidu的值为：&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 4、获取多个键的值  </span><br><span class="line">    result &#x3D; self.redis_obj.hmget(&quot;website&quot;, &quot;baidu&quot;, &quot;alibaba&quot;)  </span><br><span class="line">    print(&quot;多个键的值为:&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 5、查看hash表中的所有值  </span><br><span class="line">    result &#x3D; self.redis_obj.hgetall(&#39;website&#39;)  </span><br><span class="line">    print(&quot;哈希表中所有的键值对为：&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 6、哈希表中所有键列表  </span><br><span class="line">    # [&#39;baidu&#39;, &#39;google&#39;, &#39;tencent&#39;, &#39;alibaba&#39;]  </span><br><span class="line">    result &#x3D; self.redis_obj.hkeys(&quot;website&quot;)  </span><br><span class="line">    print(&quot;哈希表，所有的键（列表）为:&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 7、哈希表中所有的值列表  </span><br><span class="line">    # [&#39;www.alibababaidu.com&#39;, &#39;www.google.com&#39;, &#39;www.qq.com&#39;, &#39;www.taobao.com&#39;]  </span><br><span class="line">    result &#x3D; self.redis_obj.hvals(&quot;website&quot;)  </span><br><span class="line">    print(&quot;哈希表，所有的值（列表）为:&quot;, result)  </span><br><span class="line">  </span><br><span class="line">    # 8、判断某一个键是否存在  </span><br><span class="line">    result &#x3D; self.redis_obj.hexists(&quot;website&quot;, &quot;alibaba&quot;)  </span><br><span class="line">    print(&#39;alibaba这个键是否存在:&#39;, result)  </span><br><span class="line">  </span><br><span class="line">    # 9、删除某一个键值对  </span><br><span class="line">    self.redis_obj.hdel(&quot;website&quot;, &#39;baidu&#39;)  </span><br><span class="line">    print(&#39;删除baidu键值对后，哈希表的数据包含：&#39;, self.redis_obj.hgetall(&#39;website&#39;))  </span><br><span class="line">  </span><br><span class="line">    # 10、哈希表中键值对个数  </span><br><span class="line">    count &#x3D; self.redis_obj.hlen(&quot;website&quot;)  </span><br><span class="line">    print(&#39;哈希表键值对一共有：&#39;, count)  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>5、操作事务管道</p>
<p>Redis 支持事务管道操作，能够将几个操作统一提交执行</p>
<p>操作步骤是：</p>
<ul>
<li><p>首先，定义一个事务管道</p>
</li>
<li><p>然后通过事务对象去执行一系列操作</p>
</li>
<li><p>提交事务操作，结束事务操作</p>
</li>
</ul>
<p>下面通过一个简单的例子来说明：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">def manage_steps(self):  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    执行事务操作  </span><br><span class="line">    :return:  </span><br><span class="line">    &quot;&quot;&quot;  </span><br><span class="line">    # 1、定义一个事务管道  </span><br><span class="line">    self.pip &#x3D; self.redis_obj.pipeline()  </span><br><span class="line">  </span><br><span class="line">    # 定义一系列操作  </span><br><span class="line">    self.pip.set(&#39;age&#39;, 18)  </span><br><span class="line">  </span><br><span class="line">    # 增加一岁  </span><br><span class="line">    self.pip.incr(&#39;age&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 减少一岁  </span><br><span class="line">    self.pip.decr(&#39;age&#39;)  </span><br><span class="line">  </span><br><span class="line">    # 执行上面定义3个步骤的事务操作  </span><br><span class="line">    self.pip.execute()  </span><br><span class="line">  </span><br><span class="line">    # 判断  </span><br><span class="line">    print(&#39;通过上面一些列操作，年龄变成:&#39;, self.redis_obj.get(&#39;age&#39;))  </span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="4-最后"><a href="#4-最后" class="headerlink" title="4.最后"></a>4.最后</h2><p>本篇文章通过 Python 实现了对 Redis 常见数据的操作，受限于篇幅，没法对 Redis 中一些不常用的方法没法进行展开说明</p>
<p>我已经将文中全部源码上传到后台，关注公众号后回复「 <strong>dball</strong> 」即可获得全部源码</p>
<p>如果你觉得文章还不错，请大家 <strong>点赞、分享、留言</strong> 下，因为这将是我持续输出更多优质文章的最强动力！</p>
<h1 id="Python操作Redis大全"><a href="#Python操作Redis大全" class="headerlink" title="Python操作Redis大全"></a>Python操作Redis大全</h1><p>一、字符串 strings</p>
<p>Python操作Redis的redis模块对字符串（string）的主要操作函数包括：SET、GET、GETSET、SETEX、SETNX、MSET、MSETNX、INCR(INCRBY,DECR,DECRBY在python中庸同一个函数incr实现)、APPEND、SETRANGE、STRLEN。函数说明如下：</p>
<ol>
<li><p><strong>SET</strong>： 为指定的键（key）设置值（value）， set(self, name, value, **kwargs)。</p>
</li>
<li><p><strong>GET</strong>：获取指定键（key）绑定的值（value），get(self, name)。</p>
</li>
<li><p><strong>GETSET</strong>：为指定的键（key）设置新的值（value），并返回旧的值（old Value），getset(self, name, value)</p>
</li>
<li><p><strong>SETEX</strong>：为指定的键（key）设置过期以秒（second）计的过期时间，setex(self, name, value, time)</p>
</li>
<li><p><strong>SETNX</strong>：键（key）不存在时，为键（key）指定值（value），setnx(self, name, value)</p>
</li>
<li><p><strong>MSET</strong>：一次性设置多个键-值(key-value)对,函数设置的键-值对（即mapping所指内容）数据要以Python字典数据类型传入，mset(self, mapping)</p>
</li>
<li><p><strong>MSETNX</strong>：键-值(key-value)对不存在时，设置键-值（key-value）对,msetnx(self, mapping)，mapping值参考6</p>
</li>
<li><p><strong>INCR</strong>：自增函数，默认步长为1，通过对步长（amount）大小以及字符的控制实现了INCRBY（amount&gt;=1）、DECR（amount=-1）、DECRBY（amount&lt;=-1）等函数功能，incr(self, name, amount=1)</p>
</li>
<li><p><strong>APPEND</strong>：为指定的字符串追加值，若不存在则直接创建，append(self, key, value)</p>
</li>
<li><p><strong>SETRANGE</strong>：用 value 参数覆写给定 key 所储存的字符串值，从偏移量 offset 开始，setrange(self, name, offset, value)</p>
</li>
<li><p><strong>STRLEN</strong>：返回字符串的长度，当name不存在时返回0，strlen(self, name)</p>
</li>
</ol>
<p>示例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;python  </span><br><span class="line"># -*- coding:utf-8 -*-  </span><br><span class="line"># __author__ &#x3D; &#39;Jack&#39;  </span><br><span class="line">  </span><br><span class="line">pool &#x3D; redis.ConnectionPool(host&#x3D;&#39;127.0.0.1&#39;, port&#x3D;6379)  </span><br><span class="line">r &#x3D; redis.Redis(connection_pool&#x3D;pool)  </span><br><span class="line">r.flushall()  # 清空Redis  </span><br><span class="line">  </span><br><span class="line">r.setex(&#39;name&#39;, value&#x3D;&#39;liaogx&#39;, time&#x3D;2)  # 设置新值，过期时间为3s  </span><br><span class="line">r.mset(k1 &#x3D; &#39;v1&#39;, k2 &#x3D; &#39;v2&#39;, k3 &#x3D; &#39;v3&#39;)  # 批量设置新值  </span><br><span class="line">print(r.mget(&#39;k1&#39;, &#39;k2&#39;, &#39;k3&#39;, &#39;k4&#39;))  # 批量获取新值  </span><br><span class="line">print(r.getset(&#39;name&#39;, &#39;liaogaoxiang&#39;))  # 设置新值并获取原来的值  </span><br><span class="line">print(r.getrange(&#39;name&#39;, 0, 1))  # 获取子序列 0 &lt;&#x3D; x &lt;&#x3D; 1  </span><br><span class="line">r.setrange(&#39;name&#39;, 0, &#39;LIAO&#39;)  # 修改字符串内容，从指定字符串索引开始向后替换（新值太长时，则向后添加），返回值的长度  </span><br><span class="line">i &#x3D; 0  </span><br><span class="line">while i &lt; 4:  </span><br><span class="line">    print(r.get(&#39;name&#39;))  </span><br><span class="line">    time.sleep(1)  </span><br><span class="line">    i +&#x3D; 1  </span><br><span class="line">source &#x3D; &#39;foo&#39;  </span><br><span class="line">r.set(&#39;n1&#39;, source)  </span><br><span class="line">r.setbit(&#39;n1&#39;, 7, 1)  </span><br><span class="line">&#39;&#39;&#39;  </span><br><span class="line">注：如果在Redis中有一个对应： n1 &#x3D; &quot;foo&quot;，  </span><br><span class="line">    那么字符串foo的二进制表示为：01100110 01101111 01101111  </span><br><span class="line">    所以，如果执行 setbit(&#39;n1&#39;, 7, 1)，则就会将第7位设置为1，  </span><br><span class="line">    那么最终二进制则变成 01100111 01101111 01101111，即：&quot;goo&quot;  </span><br><span class="line">&#39;&#39;&#39;  </span><br><span class="line">print(r.get(&#39;n1&#39;))  </span><br><span class="line">print(r.getbit(&#39;n1&#39;, 7))  # 获取n1对应的值的二进制表示中的某位的值 （0或1）  </span><br><span class="line">r.set(&#39;n2&#39;, &#39;廖高祥&#39;)  </span><br><span class="line">print(r.strlen(&#39;n2&#39;))  # 返回对应的字节长度（一个汉字3个字节）  </span><br><span class="line">r.set(&#39;num&#39;, 1)  </span><br><span class="line">r.incr(&#39;num&#39;, amount&#x3D;10)  </span><br><span class="line">r.decr(&#39;num&#39;, amount&#x3D;1)  </span><br><span class="line">print(r.get(&#39;num&#39;))  # 自增num对应的值，当name不存在时，则创建name＝amount，否则，则自增。  </span><br><span class="line">r.append(&#39;num&#39;, 111)  </span><br><span class="line">print(r.get(&#39;num&#39;))  # 在redis num对应的值后面追加内容</span><br></pre></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">[b&#39;v1&#39;, b&#39;v2&#39;, b&#39;v3&#39;, None]  </span><br><span class="line">b&#39;liaogx&#39;  </span><br><span class="line">b&#39;li&#39;  </span><br><span class="line">b&#39;LIAOgaoxiang&#39;  </span><br><span class="line">b&#39;LIAOgaoxiang&#39;  </span><br><span class="line">b&#39;LIAOgaoxiang&#39;  </span><br><span class="line">b&#39;LIAOgaoxiang&#39;  </span><br><span class="line">b&#39;goo&#39;  </span><br><span class="line">1  </span><br><span class="line">9  </span><br><span class="line">b&#39;10&#39;  </span><br><span class="line">b&#39;10111&#39;</span><br></pre></td></tr></table></figure>

<p><strong>二、列表 lists</strong></p>
<p>Python操作Redis主要利用了redis模块来实现，list表操作函数主要模拟了Redis操作命令LPUSH，LRANGE，LINDEX，BLPOP，BRPOP。函数说明如下：</p>
<ol>
<li><p><strong>lpush</strong>函数实现了从向指定redis列表头部压入数据功能，<code>lpush key value</code></p>
</li>
<li><p><strong>lrange</strong>获取列表指定范围的函数，<code>lrange key start end</code></p>
</li>
<li><p><strong>lindex</strong>根据列表下标量获取列表元素值， <code>lindex key index</code></p>
</li>
<li><p><strong>blpop</strong>从列表头部取出第一个元素，返回该元素值并从列表删除（l代表left，左边）</p>
</li>
<li><p><strong>brpop</strong>从列表尾部取出第一个元素，返回该元素值并从列表删除（r代表right，右边）</p>
</li>
<li><p><strong>LPUSHX、RPUSHX</strong>以及其他一些Redis列表（List）函数目前版本无法实现，如有可实现方法博客代码事例将会得到更新。</p>
</li>
</ol>
<p>示例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;python  </span><br><span class="line"># -*- coding:utf-8 -*-  </span><br><span class="line"># __author__ &#x3D; &#39;Jack&#39;  </span><br><span class="line">  </span><br><span class="line">pool &#x3D; redis.ConnectionPool(host&#x3D;&#39;127.0.0.1&#39;, port&#x3D;6379)  </span><br><span class="line">r &#x3D; redis.Redis(connection_pool&#x3D;pool)  </span><br><span class="line">r.flushall()  # 清空Redis  </span><br><span class="line">  </span><br><span class="line">r.lpush(&#39;oo&#39;, 11)  # 保存顺序为: 33,22,11  </span><br><span class="line">r.lpushx(&#39;oo&#39;, 00)  # 在name对应的list中添加元素，只有name已经存在时，值添加到列表的最左边  </span><br><span class="line">print(r.llen(&#39;oo&#39;))  # name对应的list元素的个数  </span><br><span class="line">  </span><br><span class="line">r.linsert(&#39;oo&#39;, &#39;before&#39;, 11, 99)  # 在11之前插入值99  </span><br><span class="line">r.lset(&#39;oo&#39;, 1, 88)  # 对name对应的list中的某一个索引位置重新赋值  </span><br><span class="line">print(r.lrange(&#39;oo&#39;, 0, -1))  # 在name对应的列表分片获取数据  </span><br><span class="line">  </span><br><span class="line">r.lrem(&#39;oo&#39;, 88, num&#x3D;1)  # 在name对应的list中删除指定的值.num&#x3D;0，删除列表中所有的指定值；num&#x3D;2,从前到后，删除2个；num&#x3D;-2,从后向前，删除2个  </span><br><span class="line">print(r.lrange(&#39;oo&#39;, 0, -1))  </span><br><span class="line">  </span><br><span class="line">print(r.lpop(&#39;oo&#39;))  # 在name对应的列表的左侧获取第一个元素并在列表中移除，返回值则是第一个元素  </span><br><span class="line">print(r.lindex(&#39;oo&#39;, 0))  # 在name对应的列表中根据索引获取列表元素  </span><br><span class="line">r.lpush(&#39;l1&#39;, 11)  # index为0  </span><br><span class="line">r.rpush(&#39;l1&#39;, 22)  </span><br><span class="line">r.rpush(&#39;l1&#39;, 33)  </span><br><span class="line">r.rpush(&#39;l1&#39;, 44)  </span><br><span class="line">r.rpush(&#39;l1&#39;, 55)  # index为4  </span><br><span class="line">r.ltrim(&#39;l1&#39;, 1, 3)  # 在name对应的列表中移除没有在[start-end]索引之间的值  </span><br><span class="line">print(r.lrange(&#39;l1&#39;, 0, -1))  </span><br><span class="line">  </span><br><span class="line">r.rpoplpush(&#39;l1&#39;, &#39;l1&#39;)  # 从一个列表取出最右边的元素，同时将其添加至另一个列表的最左边;src要取数据的列表的name, dst要添加数据的列表的name  </span><br><span class="line">print(r.lrange(&#39;l1&#39;, 0, -1))  </span><br><span class="line">  </span><br><span class="line">r.brpoplpush(&#39;l1&#39;, &#39;l1&#39;, timeout&#x3D;3)  # # timeout，当src对应的列表中没有数据时，阻塞等待其有数据的超时时间（秒），0 表示永远阻塞  </span><br><span class="line">print(r.lrange(&#39;l1&#39;, 0, -1))  </span><br><span class="line">  </span><br><span class="line">print(r.blpop(&#39;l1&#39;, 3))  # 从列表头部取出第一个元素，返回该元素值并从列表删除（l代表left，左边）  </span><br><span class="line">print(r.lrange(&#39;l1&#39;, 0, -1))  </span><br><span class="line">&#39;&#39;&#39;  </span><br><span class="line">    # 由于redis类库中没有提供对列表元素的增量迭代，如果想要循环name对应的列表的所有元素，那么就需要：  </span><br><span class="line">    # 1、获取name对应的所有列表  </span><br><span class="line">    # 2、循环列表  </span><br><span class="line">    # 但是，如果列表非常大，那么就有可能在第一步时就将程序的内容撑爆，所有有必要自定义一个增量迭代的功能：  </span><br><span class="line">&#39;&#39;&#39;  </span><br><span class="line">print(&#39;自定义增量迭代：&#39;)  </span><br><span class="line">r.flushall()  </span><br><span class="line">r.lpush(&#39;l1&#39;, 11)  # index为0  </span><br><span class="line">r.rpush(&#39;l1&#39;, 22)  </span><br><span class="line">r.rpush(&#39;l1&#39;, 33)  </span><br><span class="line">r.rpush(&#39;l1&#39;, 44)  </span><br><span class="line">r.rpush(&#39;l1&#39;, 55)  # index为4  </span><br><span class="line">  </span><br><span class="line">def list_iter(name):  </span><br><span class="line">    list_count &#x3D; r.llen(name)  </span><br><span class="line">    for index in range(list_count):  </span><br><span class="line">        yield r.lindex(name, index)  </span><br><span class="line">  </span><br><span class="line">for item in list_iter(&#39;l1&#39;):  </span><br><span class="line">    print(item)</span><br></pre></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">2  </span><br><span class="line">[b&#39;0&#39;, b&#39;88&#39;, b&#39;11&#39;]  </span><br><span class="line">[b&#39;0&#39;, b&#39;11&#39;]  </span><br><span class="line">b&#39;0&#39;  </span><br><span class="line">b&#39;11&#39;  </span><br><span class="line">[b&#39;22&#39;, b&#39;33&#39;, b&#39;44&#39;]  </span><br><span class="line">[b&#39;44&#39;, b&#39;22&#39;, b&#39;33&#39;]  </span><br><span class="line">[b&#39;33&#39;, b&#39;44&#39;, b&#39;22&#39;]  </span><br><span class="line">(b&#39;l1&#39;, b&#39;33&#39;)  </span><br><span class="line">[b&#39;44&#39;, b&#39;22&#39;]  </span><br><span class="line">自定义增量迭代：  </span><br><span class="line">b&#39;11&#39;  </span><br><span class="line">b&#39;22&#39;  </span><br><span class="line">b&#39;33&#39;  </span><br><span class="line">b&#39;44&#39;  </span><br><span class="line">b&#39;55&#39;</span><br></pre></td></tr></table></figure>

<p><strong>三、集合 sets</strong></p>
<p>Redis 数据库集合对象(set object)是由string类型的无重复元素的无需集合，底层编码可以是intset或者hashtable。intset编码的集合对象用整数集合最为底层实现，所有对象元素保存在整数集合中。Python的redis模块实现了 SADD、SCARD 、SDIFF 、SDIFFSTORE、SINTER 、SINTERSTORE、SISMEMBER 、SMEMBERS 、SMOVE、SPOP、SRANDMEMBER、SREM、SUNION、SUNIONSTORE操作命令的基本用法。函数说明如下：</p>
<ol>
<li><p><strong>SADD</strong>：向集合对象添加成员，sadd(self, name, value)</p>
</li>
<li><p><strong>SCARD</strong>：获取集合元素个数，scard(self, name)</p>
</li>
<li><p><strong>SDIFF</strong>：返回给定多个集合对象的差集(set key1-set key2..-set keyn)，从左到右计算集合差集，sdiff(self, keys, *args)</p>
</li>
<li><p><strong>SDIFFSTORE</strong>：返回给定给定多个集合对象的差集并存储在目标（dest）集合中，sdiffstore(self, dest, keys, *args)</p>
</li>
<li><p><strong>SINTER</strong>：返回给定所有集合（keys, <em>args）的交集, sinter(self, keys,</em> args)</p>
</li>
<li><p><strong>SINTERSTORE</strong>：返回给定所有集合（keys, <em>args）的交集并存储在 集合(dest) 中, sinterstore(self, dest, keys,</em> args)</p>
</li>
<li><p><strong>SISMEMBER</strong>：判断 value元素是否是集合 name 的成员,返回布尔逻辑值True或者False，sismember(self, name, value)</p>
</li>
<li><p><strong>SMEMBERS</strong>：返回集合中所元素值的Python集合类型数据，smembers(self, name)</p>
</li>
<li><p><strong>SMOVE</strong>：将元素value从集合src移动到 集合 dest。若元素value在集合src中不存在，则集合dest中不会添加元素value， smove(self, src, dest, value)</p>
</li>
<li><p><strong>SPOP</strong>：移除并返回集合中的一个随机元素, spop(self, name)</p>
</li>
<li><p><strong>SRANDMEMBER</strong>：返回集合中一个随机数，但是不做移除操作, srandmember(self, name)。从Redis 2.6 版本开始， 在命令行下Srandmember 命令接受可选返回元素数量的参数 redis&gt;SRANDMEMBER name count</p>
</li>
<li><p><strong>SREM</strong>：移除集合中一个元素，srem(self, name, value)，redis模块任然沿用Redis 2.4 版本以前的只接受单个元素的用法。</p>
</li>
<li><p><strong>SUNION</strong>：返回所有给定集合的并集中所有元素，sunion(self, keys, *args)</p>
</li>
<li><p><strong>SUNIONSTORE</strong>：所有给定集合的并集存储在集合dest 中, sunionstore(self, dest, keys, *args)</p>
</li>
<li><p><strong>SSCAN</strong>：迭代集合中的元素，sscan(self, name, cursor=0, match=None, count=None)</p>
</li>
</ol>
<p>示例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;python  </span><br><span class="line"># -*- coding:utf-8 -*-  </span><br><span class="line"># __author__ &#x3D; &#39;Jack&#39;  </span><br><span class="line">  </span><br><span class="line">pool &#x3D; redis.ConnectionPool(host&#x3D;&#39;127.0.0.1&#39;, port&#x3D;6379)  </span><br><span class="line">r &#x3D; redis.Redis(connection_pool&#x3D;pool)  </span><br><span class="line">r.flushall()  # 清空Redis  </span><br><span class="line">  </span><br><span class="line">r.sadd(&#39;s1&#39;, &#39;v1&#39;, &#39;v1&#39;, &#39;v2&#39;, &#39;v3&#39;)  # name对应的集合中添加元素  </span><br><span class="line">r.sadd(&#39;s2&#39;, &#39;v2&#39;, &#39;v4&#39;)  # name对应的集合中添加元素  </span><br><span class="line">print(r.scard(&#39;s1&#39;))  # 获取name对应的集合中元素个数  </span><br><span class="line">print(r.sdiff(&#39;s1&#39;, &#39;s2&#39;))  #在第一个name对应的集合中且不在其他name对应的集合的元素集合  </span><br><span class="line">  </span><br><span class="line">r.sdiffstore(&#39;s3&#39;, &#39;s1&#39;, &#39;s2&#39;)  # 获取第一个name对应的集合中且不在其他name对应的集合，再将其新加入到dest对应的集合中  </span><br><span class="line">print(r.smembers(&#39;s3&#39;))  # 获取s3对应的集合的所有成员  </span><br><span class="line">  </span><br><span class="line">print(r.sinter(&#39;s1&#39;, &#39;s2&#39;))  # 获取s1, s2对应集合的交集  </span><br><span class="line">r.sinterstore(&#39;s4&#39;, &#39;s1&#39;, &#39;s2&#39;)  # 获取s1, s2对应集合的交集，并将其存放到集合是s4中  </span><br><span class="line">print(r.smembers(&#39;s4&#39;))  </span><br><span class="line">  </span><br><span class="line">print(r.sunion(&#39;s1&#39;, &#39;s2&#39;))  # 获取s1, s2对应集合的并集  </span><br><span class="line">  </span><br><span class="line">r.sunionstore(&#39;s5&#39;, &#39;s1&#39;, &#39;s2&#39;)  # 获取s1, s2对应集合的交集，并将其存放到集合是s5中  </span><br><span class="line">print(r.smembers(&#39;s5&#39;))  </span><br><span class="line">  </span><br><span class="line">print(r.sismember(&#39;s4&#39;, &#39;v4&#39;))  # 检查value是否是name对应的集合的成员  </span><br><span class="line">  </span><br><span class="line">r.smove(&#39;s2&#39;, &#39;s1&#39;, &#39;v4&#39;)  # 将集合s2中成员v4移至集合s1中  </span><br><span class="line">print(r.smembers(&#39;s1&#39;))  </span><br><span class="line">r.srem(&#39;s1&#39;, &#39;v1&#39;)  # 在name对应的集合中删除某些值  </span><br><span class="line">  </span><br><span class="line">print(r.spop(&#39;s1&#39;))  # 从集合的右侧（尾部）移除一个成员，并将其返回 注意：集合是无序的，故结果随机！  </span><br><span class="line">  </span><br><span class="line">print(r.srandmember(&#39;s1&#39;))  # 从name对应的集合中随机获取 numbers 个元素(Redis 2.6+)</span><br></pre></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">3  </span><br><span class="line">&#123;b&#39;v3&#39;, b&#39;v1&#39;&#125;  </span><br><span class="line">&#123;b&#39;v3&#39;, b&#39;v1&#39;&#125;  </span><br><span class="line">&#123;b&#39;v2&#39;&#125;  </span><br><span class="line">&#123;b&#39;v2&#39;&#125;  </span><br><span class="line">&#123;b&#39;v3&#39;, b&#39;v2&#39;, b&#39;v4&#39;, b&#39;v1&#39;&#125;  </span><br><span class="line">&#123;b&#39;v3&#39;, b&#39;v2&#39;, b&#39;v4&#39;, b&#39;v1&#39;&#125;  </span><br><span class="line">False  </span><br><span class="line">&#123;b&#39;v3&#39;, b&#39;v2&#39;, b&#39;v4&#39;, b&#39;v1&#39;&#125;  </span><br><span class="line">b&#39;v2&#39;  </span><br><span class="line">b&#39;v3&#39;</span><br></pre></td></tr></table></figure>

<p><strong>四、有序集合 sorted sets</strong></p>
<table><thead style="box-sizing: border-box;"><tr style="box-sizing: border-box;"><th style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;text-align: left;border-top-width: 1px;border-color: rgb(230, 230, 230);word-break: normal;background-color: rgb(243, 243, 243);" width="172">命令</th><th style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;text-align: left;border-top-width: 1px;border-color: rgb(230, 230, 230);word-break: normal;background-color: rgb(243, 243, 243);" width="267">描述</th></tr></thead><tbody style="box-sizing: border-box;"><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zadd 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">向有序集合添加一个或多个成员，或者更新已存在成员的分数</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zcard 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">获取有序集合的成员数</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zcount 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">计算在有序集合中指定区间分数的成员数</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zincrby 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">有序集合中对指定成员的分数加上增量 increment</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zinterstore 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zlexcount 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">在有序集合中计算指定字典区间内成员数量</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrange 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">通过索引区间返回有序集合成指定区间内的成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrangebylex 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">通过字典区间返回有序集合的成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrangebyscore 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">通过分数返回有序集合指定区间内的成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrank 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">返回有序集合中指定成员的索引</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrem 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">移除有序集合中的一个或多个成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zremrangebylex 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">移除有序集合中给定的字典区间的所有成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zremrangebyrank 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">移除有序集合中给定的排名区间的所有成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zremrangebyscore 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">移除有序集合中给定的分数区间的所有成员</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrevrange 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">返回有序集中指定区间内的成员，通过索引，分数从高到底</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrevrangebyscore 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">返回有序集中指定分数区间内的成员，分数从高到低排序</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zrevrank 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="267">返回有序集合中指定成员的排名，有序集成员按分数值递减(从大到小)排序</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zscore 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="266">返回有序集中，成员的分数值</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zunionstore 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="266">计算给定的一个或多个有序集的并集，并存储在新的 key 中</td></tr><tr style="box-sizing: border-box;"><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="69">Redis Zscan 命令</td><td style="box-sizing: border-box;padding-right: 8px;padding-left: 8px;border-color: rgb(230, 230, 230);word-break: normal;" width="266">迭代有序集合中的元素（包括元素成员和元素分值）</td></tr></tbody></table>

<p>示例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;python  </span><br><span class="line"># -*- coding:utf-8 -*-  </span><br><span class="line"># __author__ &#x3D; &#39;Jack&#39;  </span><br><span class="line">  </span><br><span class="line">pool &#x3D; redis.ConnectionPool(host&#x3D;&#39;127.0.0.1&#39;, port&#x3D;6379)  </span><br><span class="line">r &#x3D; redis.Redis(connection_pool&#x3D;pool)  </span><br><span class="line">r.flushall()  # 清空Redis  </span><br><span class="line">  </span><br><span class="line">r.zadd(&#39;z1&#39;, &#39;11&#39;, 1, &#39;22&#39;, 2, &#39;33&#39;, 3, &#39;44&#39;, 4, &#39;55&#39;, 5, &#39;66&#39;, 6, &#39;66&#39;, 7)  # 在name对应的有序集合中添加元素  </span><br><span class="line">print(r.zcard(&#39;z1&#39;))  # 获取name对应的有序集合元素的数量  </span><br><span class="line">print(r.zcount(&#39;z1&#39;, 1, 2))  # 获取name对应的有序集合中分数 在 [min,max] 之间的个数  </span><br><span class="line">r.zincrby(&#39;z1&#39;, &#39;11&#39;, amount&#x3D;5)  # 自增name对应的有序集合的 name 对应的分数  </span><br><span class="line">print(r.zrange(&#39;z1&#39;, 0, -1, desc&#x3D;False, withscores&#x3D;True))  # 值11被排序到最后;此处表示按元素的值升序排列  </span><br><span class="line">  </span><br><span class="line">print(r.zrank(&#39;z1&#39;, 33))  # 获取某个值在 name对应的有序集合中的排行（从 0 开始）  </span><br><span class="line">  </span><br><span class="line">r.zrem(&#39;z1&#39;, &#39;66&#39;)  # 删除name对应的有序集合中值是values的成员  </span><br><span class="line">print(r.zrange(&#39;z1&#39;, 0, -1, desc&#x3D;False, withscores&#x3D;True))  </span><br><span class="line">  </span><br><span class="line">r.zremrangebyrank(&#39;z1&#39;, 0, 1)  # 根据排行范围删除  </span><br><span class="line">print(r.zrange(&#39;z1&#39;, 0, -1, desc&#x3D;False, withscores&#x3D;True))  </span><br><span class="line">  </span><br><span class="line">r.zremrangebyscore(&#39;z1&#39;, 4.5, 5.5)  # 根据分数范围删除  </span><br><span class="line">print(r.zrange(&#39;z1&#39;, 0, -1, desc&#x3D;False, withscores&#x3D;True))  </span><br><span class="line">  </span><br><span class="line">print(r.zscore(&#39;z1&#39;, 11))  # 获取name对应有序集合中 value 对应的分数  </span><br><span class="line">  </span><br><span class="line">r.zadd(&quot;zset_name&quot;, &quot;a1&quot;, 6, &quot;a2&quot;, 2, &quot;a3&quot;, 5)  </span><br><span class="line">r.zadd(&#39;zset_name1&#39;, a1&#x3D;7, b1&#x3D;10, b2&#x3D;5)  </span><br><span class="line">&#39;&#39;&#39;  </span><br><span class="line">    获取两个有序集合的交集并放入dest集合，如果遇到相同值不同分数，则按照aggregate进行操作  </span><br><span class="line">    aggregate的值为: SUM  MIN  MAX  </span><br><span class="line">&#39;&#39;&#39;  </span><br><span class="line">r.zinterstore(&#39;zset_name2&#39;, (&#39;zset_name&#39;, &#39;zset_name1&#39;), aggregate&#x3D;&#39;Sum&#39;)  </span><br><span class="line">  </span><br><span class="line">print(r.zrange(&#39;zset_name2&#39;, 0, -1, desc&#x3D;False, withscores&#x3D;True))</span><br></pre></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">6  </span><br><span class="line">2  </span><br><span class="line">[(b&#39;22&#39;, 2.0), (b&#39;33&#39;, 3.0), (b&#39;44&#39;, 4.0), (b&#39;55&#39;, 5.0), (b&#39;11&#39;, 6.0), (b&#39;66&#39;, 6.0)]  </span><br><span class="line">1  </span><br><span class="line">[(b&#39;22&#39;, 2.0), (b&#39;33&#39;, 3.0), (b&#39;44&#39;, 4.0), (b&#39;55&#39;, 5.0), (b&#39;11&#39;, 6.0)]  </span><br><span class="line">[(b&#39;44&#39;, 4.0), (b&#39;55&#39;, 5.0), (b&#39;11&#39;, 6.0)]  </span><br><span class="line">[(b&#39;44&#39;, 4.0), (b&#39;11&#39;, 6.0)]  </span><br><span class="line">6.0  </span><br><span class="line">[(b&#39;a1&#39;, 13.0)]</span><br></pre></td></tr></table></figure>

<p><strong>五、哈希 hashes</strong></p>
<p>Redis 数据库hash数据类型是一个string类型的key和value的映射表，适用于存储对象。redis 中每个hash可以存储键值对多达40亿。Python的redis模块实现了Redis哈希（Hash）命令行操作的几乎全部命令，包括HDEL、HEXISTS、HGET、HGETALL、HINCRBY、HKEYS、HLEN 、HMGET 、HMSET 、HSET 、HSETNX 、HVALS 、HINCRBYFLOAT等命令。函数说明如下：</p>
<ol>
<li><p><strong>HDEL</strong>：删除对应哈希（Hash）表的指定键（key）的字段，hdel(self, name, key)</p>
</li>
<li><p><strong>HEXISTS</strong>：检测哈希（Hash）表对应键（key）字段是否存在，返回布尔逻辑，hexists(self, name, key)</p>
</li>
<li><p><strong>HGET</strong>：获取哈希（Hash）指定键（key）对应的值，hget(self, name, key)</p>
</li>
<li><p><strong>HGETALL</strong>：获取哈希(Hash)表的键-值对（key-value pairs）,返回python字典类型数据，hgetall(self, name)</p>
</li>
<li><p><strong>HINCRBY</strong>：为哈希表（Hash）指定键（key）对应的值（key）加上指定的整数数值（int，可为负值）hincrby(self&gt;, name, key, amount=1)，Redis 中本操作的值被限制在 64 位(bit)有符号数字。</p>
</li>
<li><p><strong>HKEYS</strong>：返回哈希表（Hash）对应键（key）的数组（Python称之为列表List），hkeys(self, name)</p>
</li>
<li><p><strong>HLEN</strong>： 获取哈希表（Hash）中键-值对（key-value pairs）个数，hlen(self, name)</p>
</li>
<li><p><strong>HMGET</strong>：获取哈希表（Hash）中一个或多个给点字段的值，不存在返回nil(Redis命令行)/None(Python)，hmget(self, name, keys)，其中keys可以为列表（list）</p>
</li>
<li><p><strong>HMSET</strong>：设置对个键-值对（key-value pairs）到哈希表（Hash）中，python输入值（mapping）为字典（dictionary）类型，hmset(self, name, mapping)</p>
</li>
<li><p><strong>HSET</strong>：为哈希表（Hash）赋值，若键（key）存在值（value）则覆盖，不存在则创建，hset(self, name, key, value)</p>
</li>
<li><p><strong>HSETNX</strong>：为哈希表（Hash）不存值（value）的键（key）赋值，存在操作无效，对应值（value）无变化，hsetnx(self, name, key, value)</p>
</li>
<li><p><strong>HVALS</strong>：返回哈希表（Hash）对应值（value）的列表，hvals(self, name)</p>
</li>
<li><p><strong>HINCRBYFLOAT</strong>：为哈希表 key 中的指定字段的浮点数值加上增量 increment ，hincrbyfloat(self, name, key, amount=1.0)</p>
</li>
</ol>
<p>示例代码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">#!&#x2F;usr&#x2F;bin&#x2F;python  </span><br><span class="line"># -*- coding:utf-8 -*-  </span><br><span class="line"># __author__ &#x3D; &#39;Jack&#39;  </span><br><span class="line">  </span><br><span class="line">pool &#x3D; redis.ConnectionPool(host&#x3D;&#39;127.0.0.1&#39;, port&#x3D;6379)  </span><br><span class="line">r &#x3D; redis.Redis(connection_pool&#x3D;pool)  </span><br><span class="line">r.flushall()  # 清空Redis  </span><br><span class="line">  </span><br><span class="line">r.hset(&#39;n1&#39;, &#39;k1&#39;, &#39;v1&#39;)  # hset(name, key, value),name对应的hash中设置一个键值对（不存在，则创建；否则，修改）  </span><br><span class="line">print(r.hget(&#39;n1&#39;, &#39;k1&#39;))  </span><br><span class="line">r.hmset(&#39;n2&#39;, &#123;&#39;k1&#39;: &#39;v1&#39;, &#39;k2&#39;: &#39;v2&#39;, &#39;k3&#39;: &#39;v3&#39;&#125;)  # hmset(name, mapping),在name对应的hash中批量设置键值对  </span><br><span class="line">print(r.hmget(&#39;n2&#39;, &#39;k2&#39;))  </span><br><span class="line">print(r.hgetall(&#39;n2&#39;))  # 获取name对应hash的所有键值  </span><br><span class="line">print(r.hlen(&#39;n2&#39;))  # 获取name对应的hash中键值对的个数  </span><br><span class="line">print(r.hkeys(&#39;n2&#39;))  # 获取name对应的hash中所有的key的值  </span><br><span class="line">print(r.hvals(&#39;n2&#39;))  # 获取name对应的hash中所有的value的值  </span><br><span class="line">print(r.hexists(&#39;n2&#39;, &#39;k4&#39;)) # 检查name对应的hash是否存在当前传入的key  </span><br><span class="line">r.hdel(&#39;n2&#39;, &#39;k3&#39;)  # 将name对应的hash中指定key的键值对删除  </span><br><span class="line">r.hset(&#39;n3&#39;, &#39;k1&#39;, 1)  </span><br><span class="line">r.hincrby(&#39;n3&#39;, &#39;k1&#39;, amount&#x3D;1)  # hincrby(name, key, amount&#x3D;1),自增name对应的hash中的指定key的value的值，不存在则创建key&#x3D;amount  </span><br><span class="line">print(r.hgetall(&#39;n3&#39;))</span><br></pre></td></tr></table></figure>

<p>输出结果如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">b&#39;v1&#39;  </span><br><span class="line">[b&#39;v2&#39;]  </span><br><span class="line">&#123;b&#39;k1&#39;: b&#39;v1&#39;, b&#39;k2&#39;: b&#39;v2&#39;, b&#39;k3&#39;: b&#39;v3&#39;&#125;  </span><br><span class="line">3  </span><br><span class="line">[b&#39;k1&#39;, b&#39;k2&#39;, b&#39;k3&#39;]  </span><br><span class="line">[b&#39;v1&#39;, b&#39;v2&#39;, b&#39;v3&#39;]  </span><br><span class="line">False  </span><br><span class="line">&#123;b&#39;k1&#39;: b&#39;2&#39;&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>命令太多记不住可以参考Redis中文网，强烈建议收藏</p>
</blockquote>
<blockquote>
<p><a target="_blank" rel="noopener" href="http://www.redis.net.cn/order/">http://www.redis.net.cn/order/</a></p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line">（完）</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">看完本文有收获？请转发分享给更多人</span><br><span class="line"></span><br><span class="line">**关注「P****ython那些事」，做全栈开发工程师**</span><br><span class="line"></span><br><span class="line">![](https:&#x2F;&#x2F;mmbiz.qpic.cn&#x2F;mmbiz_png&#x2F;MQ4FoG1HmnJxVd8o6xh6HKRZCSlKw94JvO1iaZ9roHrG47uPnib9KEheJ68bp9MZq4gQbQkxOhUWUicBMTSvNWiagw&#x2F;640?wx_fmt&#x3D;jpeg&amp;tp&#x3D;webp&amp;wxfrom&#x3D;5&amp;wx_lazy&#x3D;1&amp;wx_co&#x3D;1)</span><br><span class="line"></span><br><span class="line">![](https:&#x2F;&#x2F;mmbiz.qpic.cn&#x2F;mmbiz_png&#x2F;wc7YNPm3YxU23ibAGj19P5mvODkkEB3o4wyW1PuIibq8icSVmQamWibsHpKgBxyhHSEdOHKhk1WpjbJY0xrqapicib0A&#x2F;640?wx_fmt&#x3D;png&amp;tp&#x3D;webp&amp;wxfrom&#x3D;5&amp;wx_lazy&#x3D;1&amp;wx_co&#x3D;1)</span><br><span class="line"></span><br><span class="line">点「在看」的人都变好看了哦[](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzAwOTQ4MzY1Nw&#x3D;&#x3D;&amp;mid&#x3D;2247487038&amp;idx&#x3D;1&amp;sn&#x3D;05a5cc17b013ef5605da2dfb9c0c32c7&amp;chksm&#x3D;9b5faad8ac2823ce3f66ba0d239f7875e15e527088d2d7088d2a9ed1f79c2ea9f0ed900704a8&amp;scene&#x3D;21#wechat_redirect)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line">**推荐阅读**</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">[明哥写的 200页《PyCharm 中文指南》 终于发布了](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247491716&amp;idx&#x3D;1&amp;sn&#x3D;76a9f3ad5163a9ffdbaf0fefd0259261&amp;chksm&#x3D;e8858066dff20970fa9988675154fff6a6f84793a80b8ea1d6fe5d5bbb5bc816d2feabc50664&amp;scene&#x3D;21#wechat_redirect)</span><br><span class="line"></span><br><span class="line">[《Python黑魔法指南》全新版本 v2.0 上线发布](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247490543&amp;idx&#x3D;1&amp;sn&#x3D;449a1c7adfafdd5cf37874ed67620e89&amp;chksm&#x3D;e8867b0ddff1f21b9d622ba7a53b35143cd7fbb3da0d7c091b3d2cdd71d817a4397a99fa424e&amp;scene&#x3D;21#wechat_redirect)</span><br><span class="line"></span><br><span class="line">[火了！16岁高中生做的 Python 3.9 八大新特性图](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247492838&amp;idx&#x3D;2&amp;sn&#x3D;38383eee72bc37ddd1b528800834ae93&amp;chksm&#x3D;e8858404dff20d12e01cfaf93debdbffcdc8b02c760299a01b24260504df673ad82c9246c717&amp;scene&#x3D;21#wechat_redirect)  </span><br><span class="line"></span><br><span class="line">[Python 炫技操作：模块重载的五种方法](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247492817&amp;idx&#x3D;1&amp;sn&#x3D;cfb52d1a3f88a61e7b22a63306dac0e9&amp;chksm&#x3D;e8858433dff20d25f06ac0b5b767121907a4679b9e6da0905694d15c432ba596ce7b202ec7bb&amp;scene&#x3D;21#wechat_redirect)  </span><br><span class="line"></span><br><span class="line">[15 款Python编辑器的优缺点，别再问我“选什么编辑器”啦！](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247492759&amp;idx&#x3D;1&amp;sn&#x3D;6c6e6606fd9da9d2b951bda9e8a1b223&amp;chksm&#x3D;e8858475dff20d638f4b731a44dd48fe01a68f16480bcaed2516fc7d3d56c61cc6c62afccb9d&amp;scene&#x3D;21#wechat_redirect)  </span><br><span class="line"></span><br><span class="line">[超全！我把 Python 的 200个标准库整理出来了](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247492755&amp;idx&#x3D;1&amp;sn&#x3D;c0f99bb14839677d228d029a564d457c&amp;chksm&#x3D;e8858471dff20d67bc162863a6193998f39aae3e1103a5b3015ceb79f4cea1dde4fda5d2cff3&amp;scene&#x3D;21#wechat_redirect)  </span><br><span class="line"></span><br><span class="line">[刷爆全网的动态条形图，原来5行Python代码就能实现！](http:&#x2F;&#x2F;mp.weixin.qq.com&#x2F;s?__biz&#x3D;MzIzMzMzOTI3Nw&#x3D;&#x3D;&amp;mid&#x3D;2247492725&amp;idx&#x3D;1&amp;sn&#x3D;964c45002220761dafcf537d5f9fe802&amp;chksm&#x3D;e8858497dff20d8175b87ddb1997b1dd71c91a03a92e60611718fdbf2bdbe3cee41d239b360d&amp;scene&#x3D;21#wechat_redirect)</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">长按下图  ➡   关注博主</span><br><span class="line"></span><br><span class="line">（按左边关注 Python， 按右边关注 Goalng）</span><br><span class="line"></span><br><span class="line">  </span><br><span class="line"></span><br><span class="line">![](data:image&#x2F;gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg&#x3D;&#x3D;)</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

 
      <!-- reward -->
      
      <div id="reword-out">
        <div id="reward-btn">
          打赏
        </div>
      </div>
      
    </div>
    

    <!-- copyright -->
    
    <div class="declare">
      <ul class="post-copyright">
        <li>
          <i class="ri-copyright-line"></i>
          <strong>版权声明： </strong>
          
          本博客所有文章除特别声明外，著作权归作者所有。转载请注明出处！
          
        </li>
      </ul>
    </div>
    
    <footer class="article-footer">
       
<div class="share-btn">
      <span class="share-sns share-outer">
        <i class="ri-share-forward-line"></i>
        分享
      </span>
      <div class="share-wrap">
        <i class="arrow"></i>
        <div class="share-icons">
          
          <a class="weibo share-sns" href="javascript:;" data-type="weibo">
            <i class="ri-weibo-fill"></i>
          </a>
          <a class="weixin share-sns wxFab" href="javascript:;" data-type="weixin">
            <i class="ri-wechat-fill"></i>
          </a>
          <a class="qq share-sns" href="javascript:;" data-type="qq">
            <i class="ri-qq-fill"></i>
          </a>
          <a class="douban share-sns" href="javascript:;" data-type="douban">
            <i class="ri-douban-line"></i>
          </a>
          <!-- <a class="qzone share-sns" href="javascript:;" data-type="qzone">
            <i class="icon icon-qzone"></i>
          </a> -->
          
          <a class="facebook share-sns" href="javascript:;" data-type="facebook">
            <i class="ri-facebook-circle-fill"></i>
          </a>
          <a class="twitter share-sns" href="javascript:;" data-type="twitter">
            <i class="ri-twitter-fill"></i>
          </a>
          <a class="google share-sns" href="javascript:;" data-type="google">
            <i class="ri-google-fill"></i>
          </a>
        </div>
      </div>
</div>

<div class="wx-share-modal">
    <a class="modal-close" href="javascript:;"><i class="ri-close-circle-line"></i></a>
    <p>扫一扫，分享到微信</p>
    <div class="wx-qrcode">
      <img src="//api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://example.com/2020/11/11/develop/%E7%94%A8%20Python%20%E6%93%8D%E4%BD%9C%20Redis%EF%BC%8C%E7%9C%8B%E8%BF%99%E4%B8%80%E7%AF%87%E5%B0%B1%E5%A4%9F%E4%BA%86/" alt="微信分享二维码">
    </div>
</div>

<div id="share-mask"></div>  
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/develop/" rel="tag">develop</a></li></ul>

    </footer>
  </div>

   
  <nav class="article-nav">
    
      <a href="/2020/11/11/other/%E4%B8%80%E6%96%87%E6%90%9E%E6%87%82%E8%93%9D%E7%BB%BF%E5%8F%91%E5%B8%83%E3%80%81%E7%81%B0%E5%BA%A6%E5%8F%91%E5%B8%83%E5%92%8C%E6%BB%9A%E5%8A%A8%E5%8F%91%E5%B8%83/" class="article-nav-link">
        <strong class="article-nav-caption">上一篇</strong>
        <div class="article-nav-title">
          
            一文搞懂蓝绿发布、灰度发布和滚动发布.md
          
        </div>
      </a>
    
    
      <a href="/2020/11/11/develop/%E4%B8%80%E6%AC%BE%E8%BD%BB%E9%87%8F%E7%BA%A7%EF%BC%8C%E5%8F%AF%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B%E7%9A%84%E5%BC%80%E6%BA%90%E5%90%8E%E5%8F%B0%E7%B3%BB%E7%BB%9F/" class="article-nav-link">
        <strong class="article-nav-caption">下一篇</strong>
        <div class="article-nav-title">一款轻量级，可快速上手的开源后台系统.md</div>
      </a>
    
  </nav>

   
<!-- valine评论 -->
<div id="vcomments-box">
  <div id="vcomments"></div>
</div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js"></script>
<script>
  new Valine({
    el: "#vcomments",
    app_id: "",
    app_key: "",
    path: window.location.pathname,
    avatar: "monsterid",
    placeholder: "给我的文章加点评论吧~",
    recordIP: true,
  });
  const infoEle = document.querySelector("#vcomments .info");
  if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0) {
    infoEle.childNodes.forEach(function (item) {
      item.parentNode.removeChild(item);
    });
  }
</script>
<style>
  #vcomments-box {
    padding: 5px 30px;
  }

  @media screen and (max-width: 800px) {
    #vcomments-box {
      padding: 5px 0px;
    }
  }

  #vcomments-box #vcomments {
    background-color: #fff;
  }

  .v .vlist .vcard .vh {
    padding-right: 20px;
  }

  .v .vlist .vcard {
    padding-left: 10px;
  }
</style>

 
     
</article>

</section>
      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2015-2020
        <i class="ri-heart-fill heart_icon"></i> TzWind
      </li>
    </ul>
    <ul>
      <li>
        
        
        
        由 <a href="https://hexo.io" target="_blank">Hexo</a> 强力驱动
        <span class="division">|</span>
        主题 - <a href="https://github.com/Shen-Yu/hexo-theme-ayer" target="_blank">Ayer</a>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>访问人数:<span id="busuanzi_value_site_uv"></span></s>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>浏览次数:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
        <script type="text/javascript" src='https://s9.cnzz.com/z_stat.php?id=1278069914&amp;web_id=1278069914'></script>
        
      </li>
    </ul>
  </div>
</footer>
      <div class="float_btns">
        <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

      </div>
    </main>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/ayer-side.svg" alt="Hexo"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" target="_blank" rel="noopener" href="http://www.baidu.com">百度</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/friends">友链</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/2019/about">关于我</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="搜索">
        <i class="ri-search-line"></i>
      </a>
      
      
      <a class="nav-item-link" target="_blank" href="/atom.xml" title="RSS Feed">
        <i class="ri-rss-line"></i>
      </a>
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <script>
      if (window.matchMedia("(max-width: 768px)").matches) {
        document.querySelector('.content').classList.remove('on');
        document.querySelector('.sidebar').classList.remove('on');
      }
    </script>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>请我喝杯咖啡吧~</p>
  <div class="reward-box">
    
    
  </div>
</div>
    
<script src="/js/jquery-2.0.3.min.js"></script>


<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->


<script src="/js/tocbot.min.js"></script>

<script>
  tocbot.init({
    tocSelector: '.tocbot',
    contentSelector: '.article-entry',
    headingSelector: 'h1, h2, h3, h4, h5, h6',
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer: 'main',
    positionFixedSelector: '.tocbot',
    positionFixedClass: 'is-position-fixed',
    fixedSidebarOffset: 'auto'
  });
</script>

<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css">
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->

<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script>

<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->


<script src="/js/busuanzi-2.3.pure.min.js"></script>


<!-- ClickLove -->

<!-- ClickBoom1 -->

<!-- ClickBoom2 -->

<!-- CodeCopy -->


<link rel="stylesheet" href="/css/clipboard.css">

<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>


<!-- CanvasBackground -->


    
  </div>
</body>

</html>